package org.web.abc.stockanalysis.server.helper;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import org.web.base.domain.exception.ServiceException;
import org.web.base.domain.helper.ServiceExceptionHelper;

import java.io.Closeable;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class HttpHelper {

    private static final Logger logger = Logger.getLogger(HttpHelper.class);
    private static final String DEFAULT_CHARSET = "utf-8";

    /** 连接池配置 */
    private static final PoolingHttpClientConnectionManager connManager;
    private static final RequestConfig requestConfig;
    private static final CloseableHttpClient httpClient;

    static {
        // 初始化连接池
        connManager = new PoolingHttpClientConnectionManager();
        connManager.setMaxTotal(200);               // 最大连接数
        connManager.setDefaultMaxPerRoute(50);      // 每个路由最大连接数

        // 请求配置
        requestConfig = RequestConfig.custom()
                .setConnectTimeout(60_000)              // 连接超时 60s
                .setSocketTimeout(10 * 60_000)           // 读取超时 10 分钟
                .setConnectionRequestTimeout(5_000)     // 从连接池获取连接超时 5s
                .build();
        // 创建全局 HttpClient
        httpClient = HttpClients.custom()
                .setConnectionManager(connManager)
                .setDefaultRequestConfig(requestConfig)
                .build();
    }

    /** GET 请求 */
    public static String requestByGet(String uri) throws ServiceException {
        logger.info("GET URI: " + uri);
        HttpGet get = new HttpGet(uri);
        try (CloseableHttpResponse httpResponse = httpClient.execute(get)) {
            HttpEntity entity = httpResponse.getEntity();
            String result = entity != null ? EntityUtils.toString(entity, StandardCharsets.UTF_8) : null;
            logger.info("GET result: " + result);
            return result;
        } catch (Exception e) {
            logger.error(ServiceExceptionHelper.getExceptionInfo(e));
            throw new ServiceException("GET_REQUEST_FAIL", "GET 请求访问失败: " + uri);
        }
    }

    /** POST 请求 */
    public static String requestByPost(String uri, Map<String, String> params, String charset) throws ServiceException {
        logger.info("POST URI: " + uri);
        if (StringUtils.isBlank(charset)) {
            charset = DEFAULT_CHARSET;
        }
        HttpPost post = new HttpPost(uri);

        // 构造参数
        List<NameValuePair> list = new ArrayList<>();
        if (params != null) {
            for (Map.Entry<String, String> entry : params.entrySet()) {
                list.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
            }
        }

        try {
            post.setEntity(new UrlEncodedFormEntity(list, charset));
            try (CloseableHttpResponse httpResponse = httpClient.execute(post)) {
                HttpEntity entity = httpResponse.getEntity();
                String result = entity != null ? EntityUtils.toString(entity, StandardCharsets.UTF_8) : null;
                logger.info("POST result: " + result);
                return result;
            }
        } catch (Exception e) {
            logger.error(ServiceExceptionHelper.getExceptionInfo(e));
            throw new ServiceException("POST_REQUEST_FAIL", "POST 请求访问失败: " + uri);
        }
    }

    /** 关闭连接池（应用关闭时调用） */
    public static void close() {
        closeQuietly(connManager);
        closeQuietly(httpClient);
    }

    private static void closeQuietly(Closeable closeable) {
        if (closeable != null) {
            try {
                closeable.close();
            } catch (IOException e) {
                logger.error(ServiceExceptionHelper.getExceptionInfo(e));
            }
        }
    }
}
